﻿
namespace AeonNexus.Crm.Workflow
{
    using System;
    using System.Activities;
    using System.ServiceModel;
    using Microsoft.Xrm.Sdk;
    using Microsoft.Xrm.Sdk.Workflow;
    using Microsoft.Xrm.Sdk.Client;
    using System.Linq;

    public sealed class ChangeProcessStageActivity : CodeActivity
    {
        [RequiredArgument]
        [Input("Process Name")]
        public InArgument<string> Process { get; set; }

        [RequiredArgument]
        [Input("Process Stage Name")]
        public InArgument<string> ProcessStage { get; set; }

        protected override void Execute(CodeActivityContext executionContext)
        {
          
            ITracingService tracingService = executionContext.GetExtension<ITracingService>();
            if (tracingService == null)
            {
                throw new InvalidPluginExecutionException("Failed to retrieve tracing service.");
            }
            IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
            if (context == null)
            {
                throw new InvalidPluginExecutionException("Failed to retrieve workflow context.");
            } 
            try
            {
                IOrganizationService service = executionContext.GetExtension<IOrganizationServiceFactory>().CreateOrganizationService(context.UserId);
                using (var ctx = new OrganizationServiceContext(service))
                {
                    // Get the processid using the name provided
                    var process = (from p in ctx.CreateQuery("workflow")
                                   where
                                   p.GetAttributeValue<string>("name") == Process.Get(executionContext)
                                   &&
                                   p.GetAttributeValue<OptionSetValue>("statecode").Value == 1
                                   select new 
                                   {
                                       WorkflowId = p.Id

                                   }).FirstOrDefault();
                    if (process == null)
                        throw new InvalidPluginExecutionException(String.Format("Process '{0}' not found", Process.Get(executionContext)));

                    // Get the stage id using the name provided
                    var stage = (from s in ctx.CreateQuery("processstage")
                                 where
                                 s.GetAttributeValue<string>("stagename") == ProcessStage.Get(executionContext)
                                 &&
                                 s.GetAttributeValue<EntityReference>("processid").Id == process.WorkflowId
                                 select new 
                                 {
                                     ProcessStageId = s.Id

                                 }).FirstOrDefault();
                    if (stage == null)
                        throw new InvalidPluginExecutionException(String.Format("Stage '{0}' not found", Process.Get(executionContext)));

                    // Change the stage
                    Entity updatedStage = new Entity { LogicalName = context.PrimaryEntityName, Id = context.PrimaryEntityId };
                    updatedStage["stageid"] = stage.ProcessStageId;
                    updatedStage["processid"] = process.WorkflowId;
                    service.Update(updatedStage);
                }
            }
            catch (FaultException<OrganizationServiceFault> e)
            {
                tracingService.Trace("Exception: {0}", e.ToString());
                throw;
            }
            tracingService.Trace("Exiting UpdateProcessStepAndStage.Execute(), Correlation Id: {0}", context.CorrelationId);
        }

      
    }
}